export function isEmpty(str) {
	return str === null || str === '' || str === undefined;
}

export function endWith(str, suffix) {
	var reg = new RegExp(suffix + '$');
	return reg.test(str);
}

export function startWith(str, prefix) {
	var reg = new RegExp('^' + prefix);
	return reg.test(str);
}

export function getRandomArbitrary(min, max) {
	return Math.random() * (max - min) + min;
}

export function sleep(ms) {
	return new Promise(resolve => setTimeout(resolve, ms));
}

export var bindThis = function(obj, ...args) {
	for (var k in args) {
		obj[args[k]] = obj[args[k]].bind(obj);
	}
};

export var isRemoteDebugging = () => typeof atob !== 'undefined';
export var onlyForRemoteDebug = obj => (isRemoteDebugging() ? obj : obj ? '[too long, see it in remote debug]' : undefined);

export const makeCancelable = promise => {
	let hasCanceled_ = false;

	const wrappedPromise = new Promise((resolve, reject) => {
		promise.then(
			val => (hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)),
			error => (hasCanceled_ ? reject({ isCanceled: true }) : reject(error))
		);
	});

	return {
		promise: wrappedPromise,
		cancel() {
			hasCanceled_ = true;
		},
	};
};

export const promiseTimeout = function(ms, promise, msg) {
	// console.log('ms----', ms, 'msg----', msg);
	// Create a promise that rejects in <ms> milliseconds
	let timeout = new Promise((resolve, reject) => {
		let id = setTimeout(() => {
			// console.log('checktimeout', Date.now());
			clearTimeout(id);
			reject(msg || `promise2 timeout: ${ms}ms.`);
		}, ms);
		// console.log('createtimeout', Date.now(), ms);
	});
	// console.log('promise---', promise, 'timeout----', timeout);
	// Returns a race between our timeout and the passed in promise
	return Promise.race([promise, timeout]);
};

export function convertArrayBufferToBuffer(ab) {
	var buffer = new Buffer(ab.byteLength);
	var view = new Uint8Array(ab);
	for (var i = 0; i < buffer.length; ++i) {
		buffer[i] = view[i];
	}
	return buffer;
}

export function createSocketIOSendWaitor(socket) {
	var seqAuto = 0;
	var sendAction = function(type, payload) {
		if (!socket.id) throw 'socket not connected';
		var seq = ++seqAuto;
		let action = { type, payload, seq };
		socket.emit('action', action);
		return seq;
	};
	var sendActionAndWait = async function(type, payload = {}, timeout = 3000) {
		console.log('send', type, payload);
		var seq = sendAction(type, payload);
		var listener = null;
		var pro = promiseTimeout(
			timeout,
			new Promise((fill, reject) => {
				listener = action => {
					// console.log('socket wait recv', action);
					if (action.seq == seq) {
						if (action.error) reject(action.error);
						else fill(action);
					}
				};
				socket.on('action', listener);
			}),
			`等待服务器响应${type}超时`
		);
		try {
			var ret = await pro;
			return ret;
		} catch (e) {
			throw e;
		} finally {
			socket.removeListener('action', listener);
		}
	};
	return { sendAction, sendActionAndWait };
}

export function createIntervalClicker(fn, dt, name) {
	let locked = false;

	console.log('create clicker', dt, name);
	return function(d) {
		if (locked) {
			console.log('locked clicker', name);
			return;
		}
		fn(d);
		locked = true;
		setTimeout(() => {
			locked = false;
		}, dt);
	};
}
